Remember back in Module 1.4.5 when we discussed cropping and extracting the Region of Interest (ROI) from an image?
Well, in that particular example our ROI had to be rectangular.
However, what happens if our ROI is non-rectangular?
What would you do then?
As we’ll find out in this Module, along with Module 1.4.8, a combination of bitwise operations and masking can help us extract non-rectangular ROIs from image with ease.
For now, we’ll cover the basic bitwise operations — and in the next module, we’ll learn how to utilize these bitwise operations to construct masks.
Objectives:
By the end of this topic you’ll understand the four primary bitwise operations:
- AND
- OR
- XOR
- NOT
Bitwise Operations
In this section we will review four bitwise operations: AND, OR, XOR, and NOT. These four operations, while very basic and low level, are paramount to image processing — especially when we start working with masks in Section 1.4.8.
Bitwise operations operate in a binary manner and are represented as grayscale images. A given pixel is turned “off” if it has a value of zero and it is turned “on” if the pixel has a value greater than zero.
Let’s go ahead and jump into some code:
The first few lines of code import the packages we will need: numpy and cv2 . We initialize our rectangle image as a 300 x 300 NumPy array on Line 6. We then draw a 250 x 250 white rectangle at the center of the image.
Similarly, on Line 11 we initialize another image to contain our circle, which we draw on Line 12 again centered at the center of the image, with a radius of 150 pixels.
Figure 1 below displays our two shapes:
If we consider these input images, we’ll see that they only have two pixel intensity values — either the pixel is 0 (black) or the pixel is greater than zero (white). We call images that only have two pixel intensity values binary images.
Another way to think of binary images is like an on/off switch in our living room. Imagine each pixel in the 300 x 300 image is a light switch. If the switch is off then the pixel has a value of 0. But if the pixel is on, it has a value greater than zero.
In Figure 1 above, we can see that the white pixels that comprise the rectangle and circle, respectively, all have pixels values that are on, whereas the surrounding pixels have a value of off.
Keep this notion of on/off as we demonstrate bitwise operations:
As I mentioned above, a given pixel is turned “on” if it has a value greater than zero and it is turned “off” if it has a value of zero. Bitwise functions operate on these binary conditions.
In order to utilize bitwise functions we assume (in most cases) that we are comparing two pixels (the only exception is the NOT function). We’ll compare each of the pixels and then construct our bitwise representation.
Let’s quickly review our binary operations:
- AND: A bitwise AND is true if and only if both pixels are greater than zero.
- OR: A bitwise OR is true if either of the two pixels are greater than zero.
- XOR: A bitwise XOR is true if and only if one of the two pixels is greater than zero, but not both.
- NOT: A bitwise NOT inverts the “on” and “off” pixels in an image.
On Line 21 we apply a bitwise AND to our rectangle and circle images using the cv2.bitwise_and function. As the list above mentions, a bitwise AND is true if and only if both pixels are greater than zero. The output of our bitwise AND can be seen below:
We can see that edges of our square are lost — this makes sense because our rectangle does not cover as large of an area as the circle, and thus both pixels are not “on”.
We then apply a bitwise OR on Line 29 using the cv2.bitwise_or function. A bitwise OR is true if either of the two pixels are greater than zero. Take a look at the output of the bitwise OR below:
In this case, our square and rectangle have been combined together.
Next up is the bitwise XOR function, applied on Line 36 using the cv2.bitwise_xor function. A XOR operation is true if and only if one of the two pixels is greater than zero, but, both pixels cannot be greater than zero. The output of the XOR operation is displayed in Figure 4:
Here we see that the center of the square has been removed. Again, this makes sense because an XOR operation cannot have both pixels greater than zero.
Finally, we apply the NOT function on Line 42 using the cv2.bitwise_not function. Essentially, the bitwise NOT function flips pixel values. All pixels that are greater than zero are set to zero, and all pixels that are set to zero are set to 255:
Notice how our circle has been inverted — originally the circle was white on a black background, now the circle is black on a white background.
Summary
Overall, bitwise functions are extremely simple, yet very powerful. And they are absolutely essential when we start to discuss masking in Section 1.4.8. Take the time to practice and become familiar with bitwise operations now before proceeding with the lessons. We will be making heavy use of these operations throughout the rest of this course.